;0柱面0磁道2扇区
[ORG  0x500]

[SECTION .data]
KERNEL_ADDR equ 0x1200

[SECTION .gdt]
;构建BASE与LIMIT
;0
SEG_BASE equ 0
SEG_LIMIT equ 0xfffff
;屏幕段
B8000_SEG_BASE equ 0xb8000
B8000_SEG_LIMIT equ 0x7fff

CODE_SELECTOR equ (1 << 3)
DATA_SELECTOR equ (2 << 3)
B8000_SELECTOR equ (3 << 3)
;构建gdt
gdt_base:
    dd 0,0
;代码段
gdt_code:
    dw SEG_LIMIT & 0xffff
    dw SEG_BASE & 0xffff
    db SEG_BASE >> 16 & 0xff
    ;    P_DPL_D_TYPE
    db 0b1_00_1_1000
    ;    G_DB_AVL_LIMIT
    db 0b1_1_00_0000 | (SEG_LIMIT >> 16 & 0xf)
    db SEG_BASE >> 24 & 0xf
;数据段
gdt_data:
    dw SEG_LIMIT & 0xffff
    dw SEG_BASE & 0xffff
    db SEG_BASE >> 16 & 0xff
    ;    P_DPL_D_TYPE
    db 0b1_00_1_0010
    ;    G_DB_AVL_LIMIT
    db 0b1_1_00_0000 | (SEG_LIMIT >> 16 & 0xf)
    db B8000_SEG_BASE >> 24 & 0xf

gdt_b8000:
    dw B8000_SEG_LIMIT & 0xffff
    dw B8000_SEG_BASE & 0xffff
    db B8000_SEG_BASE >> 16 & 0xff
    ;    P_DPL_D_TYPE
    db 0b1_00_1_0010
    ;    G_DB_AVL_LIMIT
    db 0b0_1_00_0000 | (B8000_SEG_LIMIT >> 16 & 0xf)
    db B8000_SEG_BASE >> 24 & 0xf
gdt_ptr:
    dw $-gdt_base
    dd gdt_base

[SECTION .text]
[BITS 16]
;nasm 汇编
global _start
_start:

    mov ax, 0
    mov ss, ax
    mov ds, ax
    mov es, ax
    mov fs, ax
    mov gs, ax
    mov si, ax

    mov si, prepare_enter_protected_mode_msg
    call print

enter_protected_mode:
    ;关中断
    cli
    xchg bx,bx
    ;加载gdt表
    lgdt [gdt_ptr]
    ;开A20
    in al, 92h
    or al, 00000010b
    out 92h, al
    ;设置保护模式
    mov eax,cr0
    or eax,1
    mov cr0,eax

    jmp CODE_SELECTOR:protected_mode


print:
    mov ah, 0x0e
    mov bh, 0
    mov bl, 0x01
.loop:
    mov al, [si]
    cmp al, 0
    jz .done
    int 0x10

    inc si
    jmp .loop
.done:
    ret

[BITS 32]
protected_mode:
    mov ax,DATA_SELECTOR
    mov ds,ax
    mov ss,ax
    mov fs,ax
    mov gs,ax

    mov esp,0x9fbff

    ;内核读入内存
    mov edi,KERNEL_ADDR
    mov ecx,3
    mov bl,60
    call read_hd

    jmp CODE_SELECTOR:KERNEL_ADDR

read_hd:
   ;0x1f2 8bit 指定读取或写入的扇区数
   mov dx, 0x1f2
   mov al, bl
   out dx, al

   ;0x1f3 8bit iba地址的低八位 0-7
   inc dx
   mov al, cl
   out dx,al

   ;0x1f4 8bit iba地址的中八位 8-15
   inc dx
   mov al, ch
   out dx,al

   ;0x1f5 8bit iba地址高八位 16-23
   inc dx
   shr ecx,16
   mov al, cl
   out dx, al

   ;0x1f6 8bit
   ;0-3 位 iba地址的24-27
   ;4 0 主盘 1 从盘
   ;5 / 7 位 固定1
   ;6 0:CHS 1:LAB
   inc dx
   shr ecx,8
   and cl, 0b1111
   mov al,0b1110_0000 ;LBA
   or al,cl
   out dx, al

   ;0x1f7 8bit 命令或状态端口
   inc dx
   mov al,0x20
   out dx,al
   ;验证状态
   ;3 0 表示磁盘未准备好与主机交换数据 1表示准备好了
   ;7 0 表示磁盘不忙 1表示磁盘繁忙
   ;8 0表示前一条指令正常执行 1表示出错
    mov cl, bl
.start_read:
    push cx ;保存loop次数

    call .wait_hd_prepare
    call read_hd_data

    pop cx ;恢复次数
    loop .start_read
.return:
    ret

;等待 不繁忙且准备好 7：0 3：1 0：0
.wait_hd_prepare:
    mov dx, 0x1f7


.check:
    in al,dx
    and al,0b1000_1000
    cmp al,0b0000_1000
    jnz .check

    ret
;读硬盘 一次2字节 256次一扇区
read_hd_data:
    mov dx,0x1f0
    mov cx,256


.read_word:
    in ax,dx
    mov [edi],ax
    add edi,2
    loop .read_word

    ret

prepare_enter_protected_mode_msg:
    db "PrePare to go into protected mode..." ,10,13, 0
